home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / strpp300.zip / STR.CPP < prev    next >
C/C++ Source or Header  |  1993-04-11  |  18KB  |  908 lines

  1. /* -------------------------------------------------------------------- */
  2. /* String++ Version 3.00                                       04/10/93 */
  3. /*                                                                      */
  4. /* Enhanced string class for Turbo C++/Borland C++.                     */
  5. /* Copyright 1991-1993 by Carl W. Moreland                              */
  6. /*                                                                      */
  7. /* str.cpp                                                              */
  8. /* -------------------------------------------------------------------- */
  9.  
  10. #include <ctype.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13.  
  14. #ifdef BCCL
  15. #include "strng.h"
  16. #else
  17. #include "str.h"
  18. #endif
  19.  
  20. const String STR_NULL = "";
  21. const String& Str = STR_NULL;
  22. const String& StrNull = STR_NULL;
  23.  
  24. unsigned String::strMinLength = 16;
  25. unsigned String::strIncLength = 8;
  26. String*  String::findIn  = 0;
  27. String&  String::findStr = (String&)StrNull;
  28. unsigned String::findPos = 0;
  29. String   String::fpFormat("%0.4f");
  30.  
  31. /* ----- Constructors/Destructors ------------------------------------- */
  32.  
  33. String::String()
  34. {
  35.   strPtr = 0;
  36.   strLen = 0;
  37.   bufferLen = 0;
  38. }
  39.  
  40. String::String(const char c, const unsigned n)
  41. {
  42.   strPtr = 0;
  43.   strLen = 0;
  44.   bufferLen = 0;
  45.   SetStr(c, n);
  46. }
  47.  
  48. String::String(const char* p)
  49. {
  50.   strPtr = 0;
  51.   strLen = 0;
  52.   bufferLen = 0;
  53.   SetStr(p);
  54. }
  55.  
  56. String::String(const char* p, const unsigned pos, const unsigned len)
  57. {
  58.   strPtr = 0;
  59.   strLen = 0;
  60.   bufferLen = 0;
  61.   SetStr(p, pos, len);
  62. }
  63.  
  64. String::String(const String& s)
  65. {
  66.   strPtr = 0;
  67.   strLen = 0;
  68.   bufferLen = 0;
  69.   SetStr(s);
  70. }
  71.  
  72. String::String(const String& s, const unsigned pos, const unsigned len)
  73. {
  74.   strPtr = 0;
  75.   strLen = 0;
  76.   bufferLen = 0;
  77.   SetStr(s, pos, len);
  78. }
  79.  
  80. String::String(const int n)
  81. {
  82.   strPtr = 0;
  83.   strLen = 0;
  84.   bufferLen = 0;
  85.   ltos((long)n);
  86. }
  87.  
  88. String::String(const long n)
  89. {
  90.   strPtr = 0;
  91.   strLen = 0;
  92.   bufferLen = 0;
  93.   ltos(n);
  94. }
  95.  
  96. String::String(const float n, const char* format)
  97. {
  98.   strPtr = 0;
  99.   strLen = 0;
  100.   bufferLen = 0;
  101.   dtos((double)n, format);
  102. }
  103.  
  104. String::String(const double n, const char* format)
  105. {
  106.   strPtr = 0;
  107.   strLen = 0;
  108.   bufferLen = 0;
  109.   dtos(n, format);
  110. }
  111.  
  112. String::~String(void)
  113. {
  114.   if(strPtr)
  115.     delete strPtr;
  116. }
  117.  
  118. /* ----- SetStr/AddStr ------------------------------------------------ */
  119.  
  120. void String::SetStr(const char c, const unsigned n)
  121. {
  122.   int i;
  123.   strLen = n;
  124.  
  125.   if(bufferLen > strLen)        // if the buffer is large enough...
  126.   {
  127.     for(i=0; i<strLen; i++)
  128.       strPtr[i] = c;            // copy n chars
  129.   }
  130.   else                    // else create a new buffer
  131.   {
  132.     if(strPtr)
  133.       delete strPtr;
  134.  
  135.     strPtr = new char[GetSize(strLen)];    // allocate the memory
  136.  
  137.     for(i=0; i<strLen; i++)
  138.       strPtr[i] = c;             // copy n chars
  139.   }
  140.   strPtr[strLen] = 0;            // add NULL termination
  141. }
  142.  
  143. void String::SetStr(const char* p)
  144. {
  145.   strLen = strlen(p);
  146.  
  147.   if(bufferLen > strLen)        // if the buffer is large enough...
  148.     memcpy(strPtr, p, strLen);        // copy the String
  149.   else                    // else create a new buffer
  150.   {
  151.     char* tmp = new char[GetSize(strLen)];
  152.     memcpy(tmp, p, strLen);        // copy the String
  153.  
  154.     if(strPtr)
  155.       delete strPtr;
  156.     strPtr = tmp;            // now make strPtr = tmp
  157.   }
  158.   strPtr[strLen] = 0;            // add NULL termination
  159. }
  160.  
  161. void String::SetStr(const char* p, const unsigned pos, const unsigned len)
  162. {
  163.   int p_len = strlen(p);
  164.  
  165.   if(pos > p_len)            // error check the start pos
  166.     return;
  167.  
  168.   strLen = p_len - pos;
  169.   if(len < strLen)            // error check the copy length
  170.     strLen = len;
  171.  
  172.   if(bufferLen > strLen)        // if the buffer is large enough...
  173.     memcpy(strPtr, p+pos, strLen);    // copy the substring
  174.   else                    // else create a new buffer
  175.   {
  176.     char* tmp = new char[GetSize(strLen)];
  177.     memcpy(tmp, p+pos, strLen);        // copy the substring
  178.  
  179.     if(strPtr)
  180.       delete strPtr;
  181.     strPtr = tmp;            // now make strPtr = tmp
  182.   }
  183.   strPtr[strLen] = 0;            // add NULL termination
  184. }
  185.  
  186. void String::SetStr(const String& s)
  187. {
  188.   strLen = s.strLen;
  189.  
  190.   if(bufferLen > strLen)        // if the buffer is large enough...
  191.     memcpy(strPtr, s.strPtr, strLen);    // copy the String
  192.   else                    // else create a new buffer
  193.   {
  194.     char* tmp = new char[GetSize(strLen)];
  195.     memcpy(tmp, s.strPtr, strLen);    // copy the String
  196.  
  197.     if(strPtr)
  198.       delete strPtr;
  199.     strPtr = tmp;            // now make strPtr = tmp
  200.   }
  201.   strPtr[strLen] = 0;            // add NULL termination
  202. }
  203.  
  204. void String::SetStr(const String& s, const unsigned pos, const unsigned len)
  205. {
  206.   if(pos > s.strLen)            // error check the start pos
  207.     return;
  208.  
  209.   strLen = s.strLen - pos;
  210.   if(len < strLen)            // error check the copy length
  211.     strLen = len;
  212.  
  213.   if(bufferLen > strLen)        // if the buffer is large enough...
  214.     memcpy(strPtr, s.strPtr+pos, strLen);  // copy the substring
  215.   else                    // else create a new buffer
  216.   {
  217.     char* tmp = new char[GetSize(len)];    // allocate new memory
  218.     memcpy(tmp, s.strPtr+pos, len);    // copy the subString
  219.  
  220.     if(strPtr)
  221.       delete strPtr;
  222.     strPtr = tmp;            // now make strPtr = tmp
  223.   }
  224.   strPtr[strLen] = 0;            // add NULL termination
  225. }
  226.  
  227. void String::AddStr(const char c)
  228. {
  229.   strLen += 1;
  230.  
  231.   if(bufferLen > strLen)        // if the buffer is large enough...
  232.     strPtr[strLen-1] = c;        // append character c
  233.   else                    // else create a new buffer
  234.   {
  235.     char* tmp = new char[GetSize(strLen)];
  236.     memcpy(tmp, strPtr, strLen-1);    // copy the original String
  237.     tmp[strLen-1] = c;            // append character c
  238.  
  239.     if(strPtr)
  240.       delete strPtr;
  241.     strPtr = tmp;            // now make strPtr = tmp
  242.   }
  243.   strPtr[strLen] = 0;            // add NULL termination
  244. }
  245.  
  246. void String::AddStr(const char* p)
  247. {
  248.   unsigned s_len = strlen(p);
  249.  
  250.   if(bufferLen > strLen+s_len)        // if the buffer is large enough...
  251.     memcpy(strPtr+strLen, p, s_len);    // append String p
  252.   else                    // else create a new buffer
  253.   {
  254.     char* tmp = new char[GetSize(strLen+s_len)];
  255.     memcpy(tmp, strPtr, strLen);    // copy the original String
  256.     memcpy(tmp+strLen, p, s_len);    // append String p
  257.  
  258.     if(strPtr)
  259.       delete strPtr;
  260.     strPtr = tmp;            // now make strPtr = tmp
  261.   }
  262.   strLen += s_len;
  263.   strPtr[strLen] = 0;            // add NULL termination
  264. }
  265.  
  266. void String::AddStr(const String& s)
  267. {
  268.   if(bufferLen > strLen + s.strLen)    // if the buffer is large enough...
  269.     memcpy(strPtr+strLen, s.strPtr, s.strLen);    // append String s
  270.   else                    // else create a new buffer
  271.   {
  272.     char* tmp = new char[GetSize(strLen+s.strLen)];
  273.     memcpy(tmp, strPtr, strLen);    // copy the original String
  274.     memcpy(tmp+strLen, s.strPtr, s.strLen);    // append String s
  275.  
  276.     if(strPtr)
  277.       delete strPtr;
  278.     strPtr = tmp;            // now make strPtr = tmp
  279.   }
  280.   strLen += s.strLen;
  281.   strPtr[strLen] = 0;            // add NULL termination
  282. }
  283.  
  284. void String::ltos(const long n)
  285. {
  286.   char num[15];
  287.   ltoa(n, num, 10);
  288.  
  289.   SetStr(num);
  290. }
  291.  
  292. void String::dtos(const double n, const char* format)
  293. {
  294.   char num[40];
  295.  
  296.   if(format[0] != 0 && fpFormat != format)
  297.     fpFormat = format;
  298.  
  299.   sprintf(num, fpFormat, n);
  300.  
  301.   SetStr(num);
  302. }
  303.  
  304. unsigned String::GetSize(unsigned n)
  305. {
  306.   bufferLen = strMinLength;        // start with strMinLength
  307.  
  308.   if(n > bufferLen)
  309.   {
  310.     while(n > bufferLen)
  311.       bufferLen += strIncLength;    // incrementally add strIncLength
  312.   }
  313.   bufferLen++;                // add one for NULL termination
  314.  
  315.   return bufferLen;
  316. }
  317.  
  318. unsigned String::SetSize(unsigned len)
  319. {
  320.   if(len < strLen)
  321.     return 0;
  322.  
  323.   bufferLen = len + 1;
  324.   char *tmp = new char[bufferLen];
  325.  
  326.   memcpy(tmp, strPtr, strLen);        // copy the original String
  327.   tmp[strLen] = 0;            // add NULL termination
  328.  
  329.   if(strPtr)                // now make strPtr = tmp
  330.     delete strPtr;
  331.   strPtr = tmp;
  332.  
  333.   return bufferLen-1;
  334. }
  335.  
  336. void String::Minimize(void)
  337. {
  338.   if(strLen < bufferLen-1)
  339.     SetSize(strLen);
  340. }
  341.  
  342. void String::SetFloatFormat(const char* format) const
  343. {
  344.   if(format[0] != 0)
  345.     fpFormat = format;
  346. }
  347.  
  348. /* -------------------------------------------------------------------- */
  349.  
  350. String& String::Right(unsigned len)
  351. {
  352.   SetStr(strPtr, strLen-len, len);
  353.   return *this;
  354. }
  355.  
  356. String& String::Left(unsigned len)
  357. {
  358.   SetStr(strPtr, 0, len);
  359.   return *this;
  360. }
  361.  
  362. String& String::Mid(unsigned pos, unsigned len)
  363. {
  364.   SetStr(strPtr, pos, len);
  365.   return *this;
  366. }
  367.  
  368. String& String::Justify(char type, unsigned len, char mode)
  369. {
  370.   if(mode&TRIM)
  371.     Trim();                // delete outter whitespace
  372.  
  373.   if(strLen >= len && !(mode&CLIP))    // check for out-of-bounds
  374.     return *this;
  375.  
  376.   if(strLen > len && (mode&CLIP))    // check for clipping
  377.   {
  378.     if(type == LEFT)
  379.       Left(len);
  380.     else if(type == CENTER)
  381.       Mid((strLen-len)/2, len);
  382.     else if(type == RIGHT)
  383.       Right(len);
  384.  
  385.     return *this;            // return clipped String
  386.   }
  387.  
  388.   if(type == LEFT)
  389.     *this = *this + String(' ', len-strLen);
  390.   else if(type == CENTER)
  391.     *this = String(' ', (len-strLen)/2) + *this +
  392.             String(' ', len - (len+strLen)/2);
  393.   else if(type == RIGHT)
  394.     *this = String(' ', len-strLen) + *this;
  395.  
  396.   strLen = strlen(strPtr);
  397.   return *this;                // return normal String
  398. }
  399.  
  400. String& String::toUpper(void)
  401. {
  402.   for(int i=0; i<strlen(strPtr); i++)
  403.     strPtr[i] = ::toupper(strPtr[i]);
  404.   return *this;
  405. }
  406.  
  407. String& String::toLower(void)
  408. {
  409.   for(int i=0; i<strlen(strPtr); i++)
  410.     strPtr[i] = ::tolower(strPtr[i]);
  411.   return *this;
  412. }
  413.  
  414. int& String::Value(int& n) const
  415. {
  416.   n = atoi(strPtr);
  417.   return n;
  418. }
  419.  
  420. long& String::Value(long& n) const
  421. {
  422.   n = atol(strPtr);
  423.   return n;
  424. }
  425.  
  426. float& String::Value(float& n) const
  427. {
  428.   n = (float)atof(strPtr);
  429.   return n;
  430. }
  431.  
  432. double& String::Value(double& n) const
  433. {
  434.   n = atof(strPtr);
  435.   return n;
  436. }
  437.  
  438. String& String::Insert(unsigned pos, const String& s)
  439. {
  440.   if(pos > strLen)
  441.     return *this;
  442.  
  443.   if(bufferLen > strLen + s.strLen)
  444.   {
  445.     memmove(strPtr+pos+s.strLen, strPtr+pos, strLen-pos);
  446.     memcpy(strPtr+pos, s.strPtr, s.strLen);
  447.   }
  448.   else
  449.   {
  450.     GetSize(strLen + s.strLen);
  451.     char* tmp = new char[bufferLen];
  452.  
  453.     memcpy(tmp, strPtr, pos);
  454.     memcpy(tmp+pos, s.strPtr, s.strLen);
  455.     memcpy(tmp+pos+s.strLen, strPtr+pos, strLen-pos);
  456.  
  457.     delete strPtr;
  458.     strPtr = tmp;
  459.   }
  460.   strLen += s.strLen;
  461.   strPtr[strLen] = 0;
  462.  
  463.   return *this;
  464. }
  465.  
  466. String& String::Delete(unsigned pos, unsigned len)
  467. {
  468.   if(pos >= strLen)
  469.     return *this;
  470.   if(len > strLen - pos)
  471.     len = strLen - pos;
  472.   if(len == 0)
  473.     len = strLen - pos;
  474.  
  475.   strLen -= len;
  476.   memmove(strPtr+pos, strPtr+pos+len, strLen-pos);
  477.   strPtr[strLen] = 0;
  478.  
  479.   return *this;
  480. }
  481.  
  482. String& String::Replace(unsigned pos, unsigned len, const String& to)
  483. {
  484.   Delete(pos, len);
  485.   Insert(pos, to);
  486.  
  487.   return *this;
  488. }
  489.  
  490. char* String::Copy(char*& p) const
  491. {
  492.   p = new char[strLen + 1];
  493.   memcpy(p, strPtr, strLen);
  494.  
  495.   return p;
  496. }
  497.  
  498. String& String::Trim(int mode, char c)
  499. {
  500.   int begin = 0;
  501.   int end = strLen-1;
  502.  
  503.   if(c == WHITESPACE)            // if we're deleting whitespaces...
  504.   {
  505.     if(mode == LEFT || mode == CENTER)    // delete leading whitespace
  506.     {
  507.       while(isspace(strPtr[begin]) && begin <= end)
  508.         begin++;
  509.     }
  510.  
  511.     if(mode == RIGHT || mode == CENTER)    // delete trailing whitespace
  512.     {
  513.       while(isspace(strPtr[end]) && end >= begin)
  514.         end--;
  515.     }
  516.   }
  517.   else                    // else a character was specified
  518.   {
  519.     if(mode == LEFT || mode == CENTER)    // delete leading characters
  520.     {
  521.       while(strPtr[begin] == c && begin <= end)
  522.         begin++;
  523.     }
  524.  
  525.     if(mode == RIGHT || mode == CENTER)    // delete trailing characters
  526.     {
  527.       while(strPtr[end] == c && end >= begin)
  528.         end--;
  529.     }
  530.   }
  531.  
  532.   SetStr(strPtr, begin, end-begin+1);
  533.   return *this;
  534. }
  535.  
  536. /* ----- Find methods ------------------------------------------------- */
  537.  
  538. int String::FindFirst(const String& s) const
  539. {
  540.   char* tmp;
  541.  
  542.   if((tmp = strstr(strPtr, s.strPtr)) != NULL)
  543.   {
  544.     findIn  = (String*)this;
  545.     findStr = s;
  546.     findPos = (int)(tmp-strPtr);
  547.   }
  548.   else
  549.   {
  550.     findStr = 0;
  551.     findPos = -1;
  552.   }
  553.  
  554.   return findPos;
  555. }
  556.  
  557. int String::FindNext(void) const
  558. {
  559.   char* tmp;
  560.  
  561.   if(findIn != this)            // wrong string
  562.     return -1;
  563.  
  564.   if((tmp = strstr(strPtr+findPos+1, findStr.strPtr)) != NULL)
  565.     findPos += (int)(tmp-(strPtr+findPos));
  566.   else
  567.   {
  568.     findStr = 0;
  569.     findPos = -1;
  570.   }
  571.  
  572.   return findPos;
  573. }
  574.  
  575. int String::FindPrev(void) const
  576. {
  577.   if(findIn != this)            // wrong string
  578.     return -1;
  579.  
  580.   for(int i = findPos-findStr.strLen; i >= 0; i--)
  581.   {
  582.     if(memcmp(strPtr+i, findStr.strPtr, findStr.strLen) == 0)
  583.     {
  584.       findPos = i;
  585.       return findPos;
  586.     }
  587.   }
  588.   findPos = -1;
  589.   return findPos;
  590. }
  591.  
  592. int String::FindLast(const String& s) const
  593. {
  594.   for(int i = strLen-s.strLen; i > 0; i--)
  595.   {
  596.     if(memcmp(strPtr+i, s.strPtr, s.strLen) == 0)
  597.     {
  598.       findIn  = (String*)this;
  599.       findStr = s;
  600.       findPos = i;
  601.       return findPos;
  602.     }
  603.   }
  604.   findIn  = 0;
  605.   findPos = -1;
  606.   return findPos;
  607. }
  608.  
  609. /* ----- Operators ---------------------------------------------------- */
  610.  
  611. String String::operator()(unsigned pos, unsigned len) const
  612. {
  613.   String tmp(strPtr, pos, len);
  614.   return tmp;
  615. }
  616.  
  617. String& String::operator=(const char c)
  618. {
  619.   SetStr(c);
  620.   return *this;
  621. }
  622.  
  623. String& String::operator=(const char* p)
  624. {
  625.   SetStr(p);
  626.   return *this;
  627. }
  628.  
  629. String& String::operator=(const String& s)
  630. {
  631.   SetStr(s);
  632.   return *this;
  633. }
  634.  
  635. String& String::operator=(const long n)
  636. {
  637.   ltos(n);
  638.   return *this;
  639. }
  640.  
  641. String& String::operator=(const double n)
  642. {
  643.   dtos(n, "");
  644.   return *this;
  645. }
  646.  
  647. String& String::operator+=(const char c)
  648. {
  649.   AddStr(c);
  650.   return *this;
  651. }
  652.  
  653. String& String::operator+=(const char* p)
  654. {
  655.   AddStr(p);
  656.   return *this;
  657. }
  658.  
  659. String& String::operator+=(const String& s)
  660. {
  661.   AddStr(s);
  662.   return *this;
  663. }
  664.  
  665. String operator+(const String& s, const char* p)
  666. {
  667.   String tmp(s);
  668.   tmp.AddStr(p);
  669.   return tmp;
  670. }
  671.  
  672. String operator+(const char* p, const String& s)
  673. {
  674.   String tmp(p);
  675.   tmp.AddStr(s);
  676.   return tmp;
  677. }
  678.  
  679. String operator+(const String& s1, const String& s2)
  680. {
  681.   String tmp(s1);
  682.   tmp.AddStr(s2);
  683.   return tmp;
  684. }
  685.  
  686. String operator*(const String& s1, const unsigned n)
  687. {
  688.   String tmp(s1);
  689.  
  690.   for(int i=1; i<n; i++)
  691.     tmp += s1;
  692.   return tmp;
  693. }
  694.  
  695. String operator*(const unsigned n, const String& s1)
  696. {
  697.   String tmp(s1);
  698.  
  699.   for(int i=1; i<n; i++)
  700.     tmp += s1;
  701.   return tmp;
  702. }
  703.  
  704. String& String::operator*=(const unsigned n)
  705. {
  706.   unsigned nlen = n*strLen;
  707.  
  708.   if(bufferLen > nlen)
  709.   {
  710.     for(int i=0; i<n; i++)
  711.       memcpy(strPtr+i*strLen, strPtr, strLen);
  712.     strPtr[nlen] = 0;
  713.   }
  714.   else
  715.   {
  716.     char *tmp = new char[nlen + 1];
  717.  
  718.     for(int i=0; i<n; i++)
  719.       memcpy(tmp+i*strLen, strPtr, strLen);
  720.     tmp[nlen] = 0;
  721.  
  722.     SetStr(tmp);
  723.   }
  724.   return *this;
  725. }
  726.  
  727. char& String::operator[](const unsigned n) const
  728. {
  729.   if(n > strLen)
  730.     return *(strPtr + strLen);
  731.   return *(strPtr + n);
  732. }
  733.  
  734. String& String::operator<<(const char c)
  735. {
  736.   AddStr(c);
  737.   return *this;
  738. }
  739.  
  740. String& String::operator<<(const char* p)
  741. {
  742.   AddStr(p);
  743.   return *this;
  744. }
  745.  
  746. String& String::operator<<(const String& s)
  747. {
  748.   AddStr(s);
  749.   return *this;
  750. }
  751.  
  752. String& String::operator<<(const long n)
  753. {
  754.   char num[15];
  755.   ltoa(n, num, 10);
  756.   AddStr(num);
  757.  
  758.   return *this;
  759. };
  760.  
  761. String& String::operator<<(const double n)
  762. {
  763.   String tmp(n);
  764.   AddStr(tmp);
  765.   return *this;
  766. };
  767.  
  768. /* -------------------------------------------------------------------- */
  769. /* AWK-style functions                                                  */
  770. /* -------------------------------------------------------------------- */
  771.  
  772. int index(const String& s, const String& t)
  773. {
  774.   int pos;
  775.   char *tmp;
  776.  
  777.   if((tmp = strstr(s, t)) != NULL)
  778.     pos = (int)(tmp-(const)s());
  779.   else
  780.     pos = -1;
  781.  
  782.   return pos;
  783. }
  784.  
  785. String substr(const String& s, unsigned pos, unsigned len)
  786. {
  787.   String tmp(s, pos, len);
  788.   return tmp;
  789. }
  790.  
  791. int split(const String& s, String*& array, const String& fs)
  792. {
  793.   int i=0, j=1, start=0;
  794.   String *tmp;
  795.  
  796.   while(i < s.Len())            // find the number of substrings
  797.   {
  798.     if(memcmp(s(i), fs(), fs.Len()) == 0)
  799.       j++;
  800.     i++;
  801.   }
  802.   tmp = new String[j];            // allocate the array of strings
  803.   i = 0;
  804.   j = 0;
  805.  
  806.   while(i < s.Len())            // fill in the array
  807.   {
  808.     if(memcmp(s(i), fs(), fs.Len()) == 0)
  809.     {
  810.       tmp[j++] = mid(s, start, i-start);
  811.       i += fs.Len();
  812.       start = i;
  813.     }
  814.     else
  815.       i++;
  816.   }
  817.   tmp[j++] = mid(s, start, i-start);
  818.  
  819.   array = tmp;
  820.   return j;
  821. }
  822.  
  823. int gsub(const String& from, const String& to, String& s, unsigned count)
  824. {
  825.   int i=0, j=0;
  826.  
  827.   while(i <= s.Len() - from.Len())
  828.   {
  829.     if(memcmp(s(i), from(), from.Len()) == 0)
  830.     {
  831.       s = left(s, i) + to + right(s, s.Len()-i-from.Len());
  832.       i += to.Len();
  833.       if(++j == count)
  834.         break;
  835.     }
  836.     else
  837.       i++;
  838.   }
  839.   return j;
  840. }
  841.  
  842. /* -------------------------------------------------------------------- */
  843. /* C-style functions                            */
  844. /* -------------------------------------------------------------------- */
  845.  
  846. String toupper(const String& s)
  847. {
  848.   String tmp(s);
  849.   tmp.toUpper();
  850.   return tmp;
  851. }
  852.  
  853. String tolower(const String& s)
  854. {
  855.   String tmp(s);
  856.   tmp.toLower();
  857.   return tmp;
  858. }
  859.  
  860. String left(const String& s, unsigned len)
  861. {
  862.   String tmp(s, 0, len);
  863.   return tmp;
  864. }
  865.  
  866. String right(const String& s, unsigned len)
  867. {
  868.   String tmp(s, s.Len()-len, len);
  869.   return tmp;
  870. }
  871.  
  872. String mid(const String& s, unsigned pos, unsigned len)
  873. {
  874.   String tmp(s, pos, len);
  875.   return tmp;
  876. }
  877.  
  878. String justify(const String& s, char type, unsigned len, char mode)
  879. {
  880.   String tmp(s);
  881.   tmp.Justify(type, len, mode);
  882.   return tmp;
  883. }
  884.  
  885. String trim(const String& s, int mode)
  886. {
  887.   String tmp(s);
  888.   tmp.Trim(mode);
  889.   return tmp;
  890. }
  891.  
  892. /* ----- Stream I/O --------------------------------------------------- */
  893.  
  894. ostream& operator<<(ostream& strm, const String& s)
  895. {
  896.   return strm << s();
  897. }
  898.  
  899. istream& operator>>(istream& strm, String& s)
  900. {
  901.   char p[256];
  902.  
  903.   strm >> p;
  904.   s = p;
  905.  
  906.   return strm;
  907. }
  908.